/**
 * 定时器类
 */
export class Timer {
  private timeouts: NodeJS.Timeout[] = []
  private intervals: NodeJS.Timeout[] = []

  /**
   * 设置一个在指定时间后执行的回调函数
   * @param callback 回调函数
   * @param ms 执行时间（可选）
   * @returns NodeJS.Timeout
   */
  setTimeout(callback: (args: void) => void, ms?: number): NodeJS.Timeout

  /**
   * 设置一个在指定时间后执行的回调函数
   * @param callback 回调函数
   * @param ms 执行时间（可选）
   * @param args 回调函数的参数
   * @returns NodeJS.Timeout
   */
  setTimeout<TArgs extends any[]>(callback: (...args: TArgs) => void, ms?: number, ...args: TArgs): NodeJS.Timeout {
    const timeout = setTimeout(callback, ms, ...args)
    this.timeouts.push(timeout)
    return timeout
  }

  /**
   * 清除指定的定时器
   * @param timeout 要清除的定时器
   */
  clearTimeout(timeout: NodeJS.Timeout) {
    clearTimeout(timeout)

    const index = this.timeouts.indexOf(timeout)
    index > -1 && this.timeouts.splice(index, 1)
  }

  /**
   * 设置一个在指定时间间隔后重复执行的回调函数
   * @param callback 回调函数
   * @param ms 执行时间间隔（可选）
   * @returns NodeJS.Timeout
   */
  setInterval(callback: (args: void) => void, ms?: number): NodeJS.Timeout

  /**
   * 设置一个在指定时间间隔后重复执行的回调函数
   * @param callback 回调函数
   * @param ms 执行时间间隔（可选）
   * @param args 回调函数的参数
   * @returns NodeJS.Timeout
   */
  setInterval<TArgs extends any[]>(callback: (...args: TArgs) => void, ms?: number, ...args: TArgs): NodeJS.Timeout {
    const interval = setInterval(callback, ms, ...args)
    this.intervals.push(interval)
    return interval
  }

  /**
   * 清除所有定时器
   */
  clearTimeouts() {
    this.timeouts.forEach(timeout => {
      clearTimeout(timeout)
    })
    this.timeouts = []
  }

  /**
   * 清除所有定时间隔
   */
  clearIntervals() {
    this.intervals.forEach(interval => {
      clearInterval(interval)
    })
    this.intervals = []
  }

  /**
   * 清除所有定时器和定时间隔
   */
  clear() {
    this.clearTimeouts()
    this.clearIntervals()
  }
}
